package com.sevntu.apvs.modeling;

import java.io.PrintWriter;
import java.util.List;
import java.util.Vector;

import com.sevntu.apvs.dModel.DModel;
import com.sevntu.apvs.duelement.Element;
import com.sevntu.apvs.duelement.ModelLogicElement;

public class Modeling {
	public static boolean modeling(DModel MyTable, int Test[][], String file) {

		Vector<Vector<Integer>> Table = new Vector<Vector<Integer>>();// Table of Event
		Vector<Integer> Result;
		boolean result = false;
		int VALofSignal[];
		int ListOfActiveElement[];
		int feedback[];
		int Tm;
		int end = 0;
		PrintWriter out = null;
		String FileOut = file;
		int step;
		int TestSuite[];
		Tm = 0; // Time of modeling
		int size = 0;
		int count = 0;
		int circuits[][] = new int[MyTable.getCircuitList().size()][5];
		for (int i = 0; i < MyTable.getCircuitList().size(); i++) {
			circuits[i][0] = MyTable.getCircuitList().get(i).getCircuitId();
			circuits[i][1] = MyTable.getCircuitList().get(i).getElemNumOut();
			circuits[i][2] = MyTable.getCircuitList().get(i).getElemContactOut();
			circuits[i][3] = MyTable.getCircuitList().get(i).getElemNumIn();
			circuits[i][4] = MyTable.getCircuitList().get(i).getElemContactIn();
		}
		for (int i = 0; i < circuits.length; i++) {
			if (circuits[i][0] > size) {
				size = circuits[i][0];
			}
			if (circuits[i][3] <= circuits[i][1])
				end++;
		}
		VALofSignal = new int[size];
		ListOfActiveElement = new int[MyTable.getElemList().size()];
		feedback = new int[size];
		VALofSignal = Init(VALofSignal, 2);
		ListOfActiveElement = Init(ListOfActiveElement, 0);
		try {
			out = new PrintWriter(FileOut);
			out.print(size);
			out.println();
			for (int testing = 0; testing < Test.length; testing++) {
				step = 0;
				count = 0;
				feedback = Init(feedback, 0);
				TestSuite = new int[Test[testing].length];
				for (int i = 0; i < TestSuite.length; i++) {
					TestSuite[i] = Test[testing][i];
				}
				do {
					if (step == 0) {
						if (testing != 0) {
							Tm = Tm + 10;
						}
						for (int i = 0; i < circuits.length; i++) {
							if (circuits[i][1] == 0) {
								Result = new Vector<Integer>();
								Result.add(Tm);
								Result.add(circuits[i][1]);
								Result.add(circuits[i][2]);
								Result.add(TestSuite[circuits[i][2] - 1]);
								Table.add(Result);
							}
						}
					}
					Tm = Table.get(0).get(0);
					for (int t = 1; t < Table.size(); t++) {
						if (Tm > Table.get(t).get(0)) {
							Tm = Table.get(t).get(0);
						}
					}
					for (int r = 0; r < Table.size(); r++) {
						if (Table.get(r).get(0) == Tm) {
							for (int i = 0; i < circuits.length; i++) {
								if (circuits[i][1] == Table.get(r).get(1) && circuits[i][2] == Table.get(r).get(2)) {
									if (VALofSignal[circuits[i][0] - 1] != Table.get(r).get(3)) {
										for (int f = 0; f < circuits.length; f++) {
											if (circuits[f][0] == circuits[i][0]) {
												if (circuits[f][3] != 0) {
													ListOfActiveElement[circuits[f][3] - 1] = 1;
												}  
												if (circuits[f][3] <= circuits[f][1]) feedback[circuits[f][0]-1] = feedback[circuits[f][0]-1] = 1;
											}
										}
									}
									VALofSignal[circuits[i][0] - 1] = Table.get(r).get(3);
								}
							}
							Table.remove(r);
							r--;
						}
					}
					out.print(Tm + " ");
					for (int j = 0; j < VALofSignal.length; j++) {
						out.print(VALofSignal[j] + " ");
					}
					out.println();
					Table = RrocessingOfLAE(MyTable.getElemList(), ListOfActiveElement, Tm, circuits, VALofSignal,
							feedback, Table);
					ListOfActiveElement = Init(ListOfActiveElement, 0);
					count = 0;
					for(int yr = 0; yr<feedback.length; yr++)
					{
					     if(feedback[yr]>=5) count++;
					}
					if(count == end && end!=0){
						for(int df = 0; df <Table.size(); df++)
						{
							Table.remove(df);
							df--;
						}
					}
					step++;
				} while (Table.size() != 0);
			}
			out.close();
			result = true;
		} catch (Exception e) {
			System.out.print(e);
		} finally {
		}
		return result;
	}

	public static int[] Init(int Massive[], int val) {
		for (int i = 0; i < Massive.length; i++) {
			Massive[i] = val;
		}
		return Massive;
	}

	public static Vector<Vector<Integer>> RrocessingOfLAE(List<Element> MyList, int Massive[], int time,
			int circuits[][], int VALofSignal[], int feedback[], Vector<Vector<Integer>> Table) {
		Vector<Integer> Result;
		int res[][];
		int T = time;
		for (int i = 0; i < Massive.length; i++) {
			if (Massive[i] == 1) {
				int InputSignal[] = new int[MyList.get(i).Ninput];
				for(int dd = 0; dd<InputSignal.length; dd++)
				{
					InputSignal[dd] = 2;
				}
				for (int j = 0; j < circuits.length; j++) {
					if (circuits[j][3] == i + 1) {
						InputSignal[circuits[j][4]-1] = VALofSignal[circuits[j][0] - 1];
					} 
				}
				for (int t = 0; t < MyList.size(); t++) {
					if (MyList.get(t).id == i + 1) {
//				if ((MyList.getElemList().get(i).Component).equals("Logic")) {
						// L.Im = new L();
						ModelLogicElement m = new ModelLogicElement(MyList.get(t), InputSignal);
						res = m.OperationModelElement();
//				} 
//				else {
//					res = L.Yak(MyList.Lisickaya.get(t), InputSignal);
//				}
						for (int n = 0; n < res[0].length; n++) {
							time = time + res[2][n];
							Result = new Vector<Integer>();
							Result.add(time);
							Result.add(i + 1);
							Result.add(res[0][n]);
							Result.add(res[1][n]);
							Table.add(Result);
							time = T;
						}
					}
				}
			}
		}
		return Table;
	}
}
